class GameAI {
    constructor(boardSize = 16) {
        this.boardSize = boardSize;
        this.aiRole = null;
        this.humanRole = null;
        this.cache = {};
    }

    // 设置玩家角色
    setRoles(playerRole) {
        this.aiRole = playerRole === 1 ? 2 : 1;
        this.humanRole = playerRole;
    }

    // 评估函数：评估当前棋盘状态的价值
    evaluateBoard(board) {
        const aiScore = this.countPatterns(board, this.aiRole);
        const humanScore = this.countPatterns(board, this.humanRole);
        return aiScore - humanScore;
    }

    // 计算特定玩家的模式分数
    countPatterns(board, player) {
        const patterns = {
            '5': 100000,  // 连五
            '4': 10000,   // 连四
            '3': 1000,    // 连三
            '2': 100,     // 连二
            '1': 10       // 连一
        };
    
        let score = 0;
        const cache = {}; // 用于记忆化的缓存对象
        const directions = [
            {dx: 0, dy: 1},   // 水平
            {dx: 1, dy: 0},   // 垂直
            {dx: 1, dy: 1},   // 对角线（左上到右下）
            {dx: 1, dy: -1}   // 对角线（右上到左下）
        ];
    
        for (let dir of directions) {
            for (let i = 0; i < this.boardSize; i++) {
                for (let j = 0; j < this.boardSize; j++) {
                    let line = [];
                    for (let k = 0; k < 5; k++) {
                        const x = i + k * dir.dx;
                        const y = j + k * dir.dy;
                        if (x < 0 || x >= this.boardSize || y < 0 || y >= this.boardSize) {
                            break;
                        }
                        line.push(board[x][y]);
                    }
                    if (line.length === 5) {
                        const positionKey = `${i}-${j}-${dir.dx}-${dir.dy}`; // 用位置和方向组成的字符串作为缓存的键
                        if (cache[positionKey]) {
                            score += cache[positionKey];
                        } else {
                            const patternScore = this.getPatternScore(line, player, patterns);
                            cache[positionKey] = patternScore;
                            score += patternScore;
                        }
                    }
                }
            }
        }
    
        // 添加额外的启发式评分
        score += this.positionalHeuristic(board, player);
        return score;
    }

    // 获取所有可用的移动
    getAvailableMoves(board) {
        let moves = [];
        for (let i = 0; i < this.boardSize; i++) {
            for (let j = 0; j < this.boardSize; j++) {
                if (board[i][j] === 0) {
                    moves.push([i, j]);
                }
            }
        }
        return moves;
    }
    positionalHeuristic(board, player) {
        let score = 0;
        const boardSize = this.boardSize;
        // 动态生成权重数组（这里以简单的对称模式生成权重，可根据实际游戏策略调整权重生成逻辑）
        const weights = new Array(boardSize * boardSize).fill(0);
        const centerWeight = boardSize / 2;
        for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
                const distanceToCenterX = Math.abs(i - centerWeight);
                const distanceToCenterY = Math.abs(j - centerWeight);
                const weight = Math.max(1, boardSize - (distanceToCenterX + distanceToCenterY));
                weights[i * boardSize + j] = weight;
            }
        }
    
        // 统计目标玩家棋子数量，仅遍历有棋子的位置获取权重累加
        const playerPositions = [];
        for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
                if (board[i][j] === player) {
                    playerPositions.push(i * boardSize + j);
                }
            }
        }
    
        for (const position of playerPositions) {
            score += weights[position];
        }
    
        return score;
    }
    // α-β剪枝算法
    minimax(board, depth, alpha, beta, maximizingPlayer) {
        const boardKey = JSON.stringify(board);
        if (this.cache[boardKey]) {
            return this.cache[boardKey];
        }
        if (depth === 0) {
            const evaluation = this.evaluateBoard(board);
            this.cache[boardKey] = evaluation;
            return evaluation;
        }
        let moves = this.getAvailableMoves(board);
        // 简单示例：根据位置启发式分数对移动进行排序（可进一步完善这个排序逻辑）
        moves.sort((a, b) => {
            const posScoreA = this.positionalHeuristic(board, maximizingPlayer ? this.aiRole : this.humanRole);
            const posScoreB = this.positionalHeuristic(board, maximizingPlayer ? this.humanRole : this.aiRole);
            return posScoreB - posScoreA;
        });
        if (maximizingPlayer) {
            let maxEval = -Infinity;
            for (let [i, j] of moves) {
                board[i][j] = this.aiRole;
                let evaluate = this.minimax(board, depth - 1, alpha, beta, false);
                board[i][j] = 0; // 回溯
                maxEval = Math.max(maxEval, evaluate);
                alpha = Math.max(alpha, evaluate);
                if (beta <= alpha) {
                    break;
                }
            }
            this.cache[boardKey] = maxEval;
            return maxEval;
        } else {
            let minEval = Infinity;
            for (let [i, j] of moves) {
                board[i][j] = this.humanRole;
                let evaluate = this.minimax(board, depth - 1, alpha, beta, true);
                board[i][j] = 0; // 回溯
                minEval = Math.min(minEval, evaluate);
                beta = Math.min(beta, evaluate);
                if (beta <= alpha) {
                    break;
                }
            }
            this.cache[boardKey] = minEval;
            return minEval;
        }
    }

    // 检查是否游戏结束
    isGameOver(board) {
        let availableMoveNum = this.getAvailableMoves(board).length;
        if(availableMoveNum > 250){
            return false;
        }
        if (this.checkWin(board, this.aiRole) || this.checkWin(board, this.humanRole)) {
            return true;
        }
        return availableMoveNum === 0; // 如果没有可用的移动则平局
    }

    findBestMove(board) {
        let bestMove = [-1, -1];
        let bestValue = -Infinity;
        const availableMoves = this.getAvailableMoves(board);
        const moveCache = {}; // 用于缓存移动在不同深度下的minimax值
        // 动态调整搜索深度
        const availableMovesCount = availableMoves.length;
        if (availableMovesCount === this.boardSize * this.boardSize){
            return [6,6];
        }
        let depth = 1;
        // if(availableMovesCount > 250){
        //     depth = 1;
        // } else if (availableMovesCount > 200) {
        //     depth = 2; // 棋盘较为空时，设置较大的深度
        // } else if (availableMovesCount > 100) {
        //     depth = 3; // 棋盘有一定棋子时，设置中等深度
        // } else {
        //     depth = 4; // 棋盘较满时，设置较小的深度
        // }
        // 简单的启发式排序，可根据更多因素完善此排序逻辑
        availableMoves.sort((a, b) => {
            const posScoreA = this.positionalHeuristic(board, this.aiRole);
            const posScoreB = this.positionalHeuristic(board, this.aiRole);
            return posScoreB - posScoreA;
        });
        let keepSearching = true;
        while (keepSearching) {
            let tempBestMove = [-1, -1];
            let tempBestValue = -Infinity;
            for (let [i, j] of availableMoves) {
                const moveKey = `${i}-${j}-${depth}`; // 以移动坐标和深度组成键，用于缓存
                if (moveCache[moveKey]) {
                    const cachedValue = moveCache[moveKey];
                    if (cachedValue > tempBestValue) {
                        tempBestMove = [i, j];
                        tempBestValue = cachedValue;
                    }
                } else {
                    board[i][j] = this.aiRole;
                    // 可以根据局面情况动态调整alpha和beta的初始值，这里简单示例
                    // const alpha = -Infinity;
                    // const beta = Infinity;
                    const alpha = -this.countPatterns(board, this.aiRole);
                    const beta = this.countPatterns(board, this.humanRole);
                    const moveVal = this.minimax(board, depth, alpha, beta, false);
                    board[i][j] = 0; // 回溯
                    if (moveVal > tempBestValue) {
                        tempBestMove = [i, j];
                        tempBestValue = moveVal;
                    }
                    moveCache[moveKey] = moveVal; // 缓存本次计算结果
                }
            }
    
            if (tempBestValue > bestValue) {
                bestMove = tempBestMove;
                bestValue = tempBestValue;
                depth++;
            } else {
                keepSearching = false;
            }
        }
    
        return bestMove;
    }
    // 获取特定模式的分数
    getPatternScore(line, player, patterns) {
        let pattern = line.join('');
        let opponent = player === this.aiRole ? this.humanRole : this.aiRole;
        // 检查是否有对手的棋子阻断
        if (pattern.includes(opponent.toString())) {
            return 0;
        }
        // 计算连子数量
        let count = pattern.split('').filter(cell => cell === player.toString()).length;
        // 返回对应的分数
        return patterns[count] || 0;
    }
    // 检查某个玩家是否获胜
    checkWin(board, player) {
        const directions = [
            {dx: 0, dy: 1},   // 水平
            {dx: 1, dy: 0},   // 垂直
            {dx: 1, dy: 1},   // 对角线（左上到右下）
            {dx: 1, dy: -1}   // 对角线（右上到左下）
        ];
        for (let i = 0; i < this.boardSize; i++) {
            for (let j = 0; j < this.boardSize; j++) {
                if (board[i][j]!== player) continue;
                for (let dir of directions) {
                    let count = 1;
                    for (let k = 1; k < 5; k++) {
                        let x = i + k * dir.dx;
                        let y = j + k * dir.dy;
                        // 严格进行边界检查，确保坐标在棋盘范围内
                        if (x < 0 || x >= this.boardSize || y < 0 || y >= this.boardSize || board[x][y]!== player) {
                            break;
                        }
                        count++;
                    }
                    if (count === 5) return true;
                }
            }
        }
        return false;
    }
}

// 初始化 GameAI 实例
const gameAI = new GameAI();

self.onmessage = function(e) {
    const { action, data } = e.data;
    switch(action) {
        case 'setRoles':
            gameAI.setRoles(data.playerRole);
            break;
        case 'findBestMove':
            const result = gameAI.findBestMove(data.board);
            self.postMessage({ type: 'bestMove', data: result });
            break;
        case 'isGameOver':
            const winResult = gameAI.isGameOver(data.board);
            self.postMessage({ type: 'gameOver', data: winResult });
            break;
        default:
            console.error('未知的操作(Unknown operation)');
    }
};